using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace TMFileManager.win32 {
    // from ShObjIdl.h
    public enum ESFGAO : uint {
        SFGAO_CANCOPY = 0x00000001,
        SFGAO_CANMOVE = 0x00000002,
        SFGAO_CANLINK = 0x00000004,
        SFGAO_LINK = 0x00010000,
        SFGAO_SHARE = 0x00020000,
        SFGAO_READONLY = 0x00040000,
        SFGAO_HIDDEN = 0x00080000,
        SFGAO_FOLDER = 0x20000000,
        SFGAO_FILESYSTEM = 0x40000000,
        SFGAO_HASSUBFOLDER = 0x80000000,
    }

    public enum ESHCONTF {
        SHCONTF_FOLDERS = 0x0020,
        SHCONTF_NONFOLDERS = 0x0040,
        SHCONTF_INCLUDEHIDDEN = 0x0080,
        SHCONTF_INIT_ON_FIRST_NEXT = 0x0100,
        SHCONTF_NETPRINTERSRCH = 0x0200,
        SHCONTF_SHAREABLE = 0x0400,
        SHCONTF_STORAGE = 0x0800
    }
    // from shlobj.h
    public enum ESHGDN {
        SHGDN_NORMAL = 0x0000,
        SHGDN_INFOLDER = 0x0001,
        SHGDN_FOREDITING = 0x1000,
        SHGDN_FORADDRESSBAR = 0x4000,
        SHGDN_FORPARSING = 0x8000,
    }

    public enum ESTRRET : int {
        eeRRET_WSTR = 0x0000,            // Use STRRET.pOleStr
        STRRET_OFFSET = 0x0001,    // Use STRRET.uOffset to Ansi
        STRRET_CSTR = 0x0002            // Use STRRET.cStr
    }

    [Flags]
    public enum SHCONTF : uint {
        SHCONTF_FOLDERS = 0x0020,   // only want folders enumerated (SFGAO_FOLDER)
        SHCONTF_NONFOLDERS = 0x0040,   // include non folders
        SHCONTF_INCLUDEHIDDEN = 0x0080,   // show items normally hidden
        SHCONTF_INIT_ON_FIRST_NEXT = 0x0100,   // allow EnumObject() to return before validating enum
        SHCONTF_NETPRINTERSRCH = 0x0200,   // hint that client is looking for printers
        SHCONTF_SHAREABLE = 0x0400,   // hint that client is looking sharable resources (remote shares)
        SHCONTF_STORAGE = 0x0800,   // include all items with accessible storage and their ancestors
    }

    [Flags]
    public enum SFGAOF : uint {
        SFGAO_CANCOPY = 0x1,                // Objects can be copied    (DROPEFFECT_COPY)
        SFGAO_CANMOVE = 0x2,                // Objects can be moved     (DROPEFFECT_MOVE)
        SFGAO_CANLINK = 0x4,                // Objects can be linked    (DROPEFFECT_LINK)
        SFGAO_STORAGE = 0x00000008,         // supports BindToObject(IID_IStorage)
        SFGAO_CANRENAME = 0x00000010,         // Objects can be renamed
        SFGAO_CANDELETE = 0x00000020,         // Objects can be deleted
        SFGAO_HASPROPSHEET = 0x00000040,         // Objects have property sheets
        SFGAO_DROPTARGET = 0x00000100,         // Objects are drop target
        SFGAO_CAPABILITYMASK = 0x00000177,
        SFGAO_ENCRYPTED = 0x00002000,         // object is encrypted (use alt color)
        SFGAO_ISSLOW = 0x00004000,         // 'slow' object
        SFGAO_GHOSTED = 0x00008000,         // ghosted icon
        SFGAO_LINK = 0x00010000,         // Shortcut (link)
        SFGAO_SHARE = 0x00020000,         // shared
        SFGAO_READONLY = 0x00040000,         // read-only
        SFGAO_HIDDEN = 0x00080000,         // hidden object
        SFGAO_DISPLAYATTRMASK = 0x000FC000,
        SFGAO_FILESYSANCESTOR = 0x10000000,         // may contain children with SFGAO_FILESYSTEM
        SFGAO_FOLDER = 0x20000000,         // support BindToObject(IID_IShellFolder)
        SFGAO_FILESYSTEM = 0x40000000,         // is a win32 file system object (file/folder/root)
        SFGAO_HASSUBFOLDER = 0x80000000,         // may contain children with SFGAO_FOLDER
        SFGAO_CONTENTSMASK = 0x80000000,
        SFGAO_VALIDATE = 0x01000000,         // invalidate cached information
        SFGAO_REMOVABLE = 0x02000000,         // is this removeable media?
        SFGAO_COMPRESSED = 0x04000000,         // Object is compressed (use alt color)
        SFGAO_BROWSABLE = 0x08000000,         // supports IShellFolder, but only implements CreateViewObject() (non-folder view)
        SFGAO_NONENUMERATED = 0x00100000,         // is a non-enumerated object
        SFGAO_NEWCONTENT = 0x00200000,         // should show bold in explorer tree
        SFGAO_CANMONIKER = 0x00400000,         // defunct
        SFGAO_HASSTORAGE = 0x00400000,         // defunct
        SFGAO_STREAM = 0x00400000,         // supports BindToObject(IID_IStream)
        SFGAO_STORAGEANCESTOR = 0x00800000,         // may contain children with SFGAO_STORAGE or SFGAO_STREAM
        SFGAO_STORAGECAPMASK = 0x70C50008,         // for determining storage capabilities, ie for open/save semantics
    }

    [Flags]
    public enum SHGNO : uint {
        SHGDN_NORMAL = 0x0000,  // default (display purpose)
        SHGDN_INFOLDER = 0x0001,  // displayed under a folder (relative)
        SHGDN_FOREDITING = 0x1000,  // for in-place editing
        SHGDN_FORADDRESSBAR = 0x4000,  // UI friendly parsing name (remove ugly stuff)
        SHGDN_FORPARSING = 0x8000,  // parsing name for ParseDisplayName()
    }

    [StructLayout(LayoutKind.Explicit, Size = 520)]
    public struct STRRETinternal {
        [FieldOffset(0)]
        public IntPtr pOleStr;

        [FieldOffset(0)]
        public IntPtr pStr;  // LPSTR pStr;   NOT USED

        [FieldOffset(0)]
        public uint uOffset;

    }

    [StructLayout(LayoutKind.Sequential)]
    public struct STRRET {
        public uint uType;
        public STRRETinternal data;
    }

    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("000214E6-0000-0000-C000-000000000046")]
    interface IShellFolder {
        // Translates a file object's or folder's display name into an item
        // identifier list.
        // Return value: error code, if any
        [PreserveSig()]
        uint ParseDisplayName(
            IntPtr hwnd,        // Optional window handle
            IntPtr pbc,         // Optional bind context that controls the
            // parsing operation. This parameter is
            // normally set to NULL.
            [In(), MarshalAs(UnmanagedType.LPWStr)]
            string pszDisplayName,  // Null-terminated UNICODE string with the
            // display name.
            out uint pchEaten,      // Pointer to a ULONG value that receives the
            // number of characters of the
            // display name that was parsed.
            out IntPtr ppidl,       // Pointer to an ITEMIDLIST pointer that receives
            // the item identifier list for
            // the object.
            ref uint pdwAttributes); // Optional parameter that can be used to
        // query for file attributes.
        // this can be values from the SFGAO enum

        // Allows a client to determine the contents of a folder by creating
        // an item identifier enumeration object and returning its
        // IEnumIDList interface.
        // Return value: error code, if any
        [PreserveSig()]
        uint EnumObjects(
            IntPtr hwnd,        // If user input is required to perform the
            // enumeration, this window handle
            // should be used by the enumeration object as
            // the parent window to take
            // user input.
            SHCONTF grfFlags,       // Flags indicating which items to include in the
            // enumeration. For a list
            // of possible values, see the SHCONTF enum.
            out IEnumIDList ppenumIDList);  // Address that receives a pointer to the
        // IEnumIDList interface of the
        // enumeration object created by this method.

        // Retrieves an IShellFolder object for a subfolder.
        // Return value: error code, if any
        [PreserveSig()]
        uint BindToObject(
            IntPtr pidl,        // Address of an ITEMIDLIST structure (PIDL)
            // that identifies the subfolder.
            IntPtr pbc,         // Optional address of an IBindCtx interface on
            // a bind context object to be
            // used during this operation.
            [In()]
            ref Guid riid,      // Identifier of the interface to return.
            //[MarshalAs(UnmanagedType.Interface)]
            out IntPtr ppv);    // Address that receives the interface pointer.

        // Requests a pointer to an object's storage interface.
        // Return value: error code, if any
        [PreserveSig()]
        uint BindToStorage(
            IntPtr pidl,        // Address of an ITEMIDLIST structure that
            // identifies the subfolder relative
            // to its parent folder.
            IntPtr pbc,         // Optional address of an IBindCtx interface on a
            // bind context object to be
            // used during this operation.
            [In()]
            ref Guid riid,      // Interface identifier (IID) of the requested
            // storage interface.
            [MarshalAs(UnmanagedType.Interface)]
            out object ppv);    // Address that receives the interface pointer
        // specified by riid.

        // Determines the relative order of two file objects or folders, given
        // their item identifier lists. Return value: If this method is
        // successful, the CODE field of the HRESULT contains one of the
        // following values (the code can be retrived using the helper function
        // GetHResultCode): Negative A
        // negative return value indicates that the first item should precede
        // the second (pidl1 < pidl2).

        // Positive A positive return value indicates that the first item should
        // follow the second (pidl1 > pidl2).  Zero A return value of zero
        // indicates that the two items are the same (pidl1 = pidl2).
        [PreserveSig()]
        int CompareIDs(
            int lParam,         // Value that specifies how the comparison
            // should be performed. The lower
            // Sixteen bits of lParam define the sorting
            // rule.
            // The upper sixteen bits of
            // lParam are used for flags that modify the
            // sorting rule. values can be from
            // the SHCIDS enum
            IntPtr pidl1,       // Pointer to the first item's ITEMIDLIST
            // structure.
            IntPtr pidl2);      // Pointer to the second item's ITEMIDLIST
        // structure.

        // Requests an object that can be used to obtain information from or interact
        // with a folder object.
        // Return value: error code, if any
        [PreserveSig()]
        uint CreateViewObject(
            IntPtr hwndOwner,       // Handle to the owner window.
            [In()]
            ref Guid riid,      // Identifier of the requested interface.
            [MarshalAs(UnmanagedType.Interface)]
            out object ppv);    // Address of a pointer to the requested
        // interface.

        // Retrieves the attributes of one or more file objects or subfolders.
        // Return value: error code, if any
        [PreserveSig()]
        uint GetAttributesOf(
            int cidl,           // Number of file objects from which to retrieve
            // attributes.
            [In(), MarshalAs(UnmanagedType.LPArray)] IntPtr[]
            apidl,          // Address of an array of pointers to ITEMIDLIST
            // structures, each of which
            // uniquely identifies a file object relative to
            // the parent folder.
            [MarshalAs(UnmanagedType.LPArray)] SFGAOF[]
            rgfInOut);          // Address of a single ULONG value that, on
        // entry,
        // contains the attributes that the caller is
        // requesting. On exit, this value contains the
        // requested attributes that are common to all
        // of the specified objects. this value can
        // be from the SFGAO enum

        // Retrieves an OLE interface that can be used to carry out actions on the
        // specified file objects or folders. Return value: error code, if any
        [PreserveSig()]
        uint GetUIObjectOf(
            IntPtr hwndOwner,       // Handle to the owner window that the client
            // should specify if it displays
            // a dialog box or message box.
            int cidl,           // Number of file objects or subfolders specified
            // in the apidl parameter.
            [In(), MarshalAs(UnmanagedType.LPArray)] IntPtr[]
            apidl,          // Address of an array of pointers to ITEMIDLIST
            // structures, each of which
            // uniquely identifies a file object or subfolder
            // relative to the parent folder.
            [In()]
            ref Guid riid,      // Identifier of the COM interface object to
            // return.
            IntPtr rgfReserved,     // Reserved.
            [MarshalAs(UnmanagedType.Interface)]
            out object ppv);    // Pointer to the requested interface.

        // Retrieves the display name for the specified file object or subfolder.
        // Return value: error code, if any
        [PreserveSig()]
        uint GetDisplayNameOf(
            IntPtr pidl,        // Address of an ITEMIDLIST structure (PIDL)
            // that uniquely identifies the file
            // object or subfolder relative to the parent
            // folder.
            SHGNO uFlags,       // Flags used to request the type of display name
            // to return. For a list of possible values.
            out STRRET pName);      // Address of a STRRET structure in which to
        // return the display name.

        // Sets the display name of a file object or subfolder, changing the item
        // identifier in the process.
        // Return value: error code, if any
        [PreserveSig()]
        uint SetNameOf(
            IntPtr hwnd,        // Handle to the owner window of any dialog or
            // message boxes that the client
            // displays.
            IntPtr pidl,        // Pointer to an ITEMIDLIST structure that
            // uniquely
            // identifies the file object
            // or subfolder relative to the parent folder.
            [In(), MarshalAs(UnmanagedType.LPWStr)]
            string pszName,     // Pointer to a null-terminated string that
            // specifies the new display name.
            SHGNO uFlags,       // Flags indicating the type of name specified by
            // the lpszName parameter. For a list of possible
            // values, see the description of the SHGNO
            // enum.
            out IntPtr ppidlOut);   // Address of a pointer to an ITEMIDLIST
        // structure
        // which receives the new ITEMIDLIST.
    }
}